/*
 * Copyright 2012-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.web.client;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;

import reactor.netty.http.client.HttpClientRequest;

import org.springframework.beans.BeanUtils;
import org.springframework.http.client.AbstractClientHttpRequestFactoryWrapper;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriTemplateHandler;

/**
 * 可用于配置和创建 {@link RestTemplate} 的构建器。提供便利方法来注册
 * {@link #messageConverters(HttpMessageConverter...) 转换器}、
 * {@link #errorHandler(ResponseErrorHandler) 错误处理器} 和
 * {@link #uriTemplateHandler(UriTemplateHandler) UriTemplateHandlers}。
 * <p>
 * 默认情况下，构建的 {@link RestTemplate} 将尝试使用最合适的
 * {@link ClientHttpRequestFactory}，如果您更愿意保持默认值，
 * 请调用 {@link #detectRequestFactory(boolean) detectRequestFactory(false)}。
 * 在典型的自动配置 Spring Boot 应用程序中，此构建器作为 bean 可用，
 * 并且可以在需要 {@link RestTemplate} 时注入。
 *
 * @author Stephane Nicoll
 * @author Phillip Webb
 * @author Andy Wilkinson
 * @author Brian Clozel
 * @author Dmytro Nosan
 * @author Kevin Strijbos
 * @author Ilya Lukyanovich
 * @since 1.4.0
 */
public class RestTemplateBuilder {

	private final RequestFactoryCustomizer requestFactoryCustomizer;

	private final boolean detectRequestFactory;

	private final String rootUri;

	private final Set<HttpMessageConverter<?>> messageConverters;

	private final Set<ClientHttpRequestInterceptor> interceptors;

	private final Supplier<ClientHttpRequestFactory> requestFactory;

	private final UriTemplateHandler uriTemplateHandler;

	private final ResponseErrorHandler errorHandler;

	private final BasicAuthentication basicAuthentication;

	private final Map<String, List<String>> defaultHeaders;

	private final Set<RestTemplateCustomizer> customizers;

	private final Set<RestTemplateRequestCustomizer<?>> requestCustomizers;

	/**
	 * 创建一个新的 {@link RestTemplateBuilder} 实例。
	 * @param customizers 在构建 {@link RestTemplate} 时应该应用的任何
	 * {@link RestTemplateCustomizer RestTemplateCustomizers}
	 */
	public RestTemplateBuilder(RestTemplateCustomizer... customizers) {
		Assert.notNull(customizers, "Customizers must not be null");
		this.requestFactoryCustomizer = new RequestFactoryCustomizer();
		this.detectRequestFactory = true;
		this.rootUri = null;
		this.messageConverters = null;
		this.interceptors = Collections.emptySet();
		this.requestFactory = null;
		this.uriTemplateHandler = null;
		this.errorHandler = null;
		this.basicAuthentication = null;
		this.defaultHeaders = Collections.emptyMap();
		this.customizers = copiedSetOf(customizers);
		this.requestCustomizers = Collections.emptySet();
	}

	private RestTemplateBuilder(RequestFactoryCustomizer requestFactoryCustomizer, boolean detectRequestFactory,
			String rootUri, Set<HttpMessageConverter<?>> messageConverters,
			Set<ClientHttpRequestInterceptor> interceptors, Supplier<ClientHttpRequestFactory> requestFactorySupplier,
			UriTemplateHandler uriTemplateHandler, ResponseErrorHandler errorHandler,
			BasicAuthentication basicAuthentication, Map<String, List<String>> defaultHeaders,
			Set<RestTemplateCustomizer> customizers, Set<RestTemplateRequestCustomizer<?>> requestCustomizers) {
		this.requestFactoryCustomizer = requestFactoryCustomizer;
		this.detectRequestFactory = detectRequestFactory;
		this.rootUri = rootUri;
		this.messageConverters = messageConverters;
		this.interceptors = interceptors;
		this.requestFactory = requestFactorySupplier;
		this.uriTemplateHandler = uriTemplateHandler;
		this.errorHandler = errorHandler;
		this.basicAuthentication = basicAuthentication;
		this.defaultHeaders = defaultHeaders;
		this.customizers = customizers;
		this.requestCustomizers = requestCustomizers;
	}

	/**
	 * 设置是否应该基于类路径检测 {@link ClientHttpRequestFactory}。默认为 {@code true}。
	 * @param detectRequestFactory 是否应该检测 {@link ClientHttpRequestFactory}
	 * @return 一个新的构建器实例
	 */
	public RestTemplateBuilder detectRequestFactory(boolean detectRequestFactory) {
		return new RestTemplateBuilder(this.requestFactoryCustomizer, detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, this.basicAuthentication, this.defaultHeaders, this.customizers,
				this.requestCustomizers);
	}

	/**
	 * 设置应该应用于每个以 {@code '/'} 开头的请求的根 URL。
	 * 由于这通过向 {@link RestTemplate} 添加 {@link UriTemplateHandler} 来工作，
	 * 根 URL 只有在使用 {@link RestTemplate} 方法的 {@code String} 变体来指定请求 URL 时才会应用。
	 * 详细信息请参见 {@link RootUriTemplateHandler}。
	 * @param rootUri 根 URI 或 {@code null}
	 * @return 一个新的构建器实例
	 */
	public RestTemplateBuilder rootUri(String rootUri) {
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, this.basicAuthentication, this.defaultHeaders, this.customizers,
				this.requestCustomizers);
	}

	/**
	 * 设置应该与 {@link RestTemplate} 一起使用的 {@link HttpMessageConverter HttpMessageConverters}。
	 * 设置此值将替换任何先前配置的转换器，在构建器上配置的任何转换器将替换 RestTemplate 的默认转换器。
	 * @param messageConverters 要设置的转换器
	 * @return 一个新的构建器实例
	 * @see #additionalMessageConverters(HttpMessageConverter...)
	 */
	public RestTemplateBuilder messageConverters(HttpMessageConverter<?>... messageConverters) {
		Assert.notNull(messageConverters, "MessageConverters must not be null");
		return messageConverters(Arrays.asList(messageConverters));
	}

	/**
	 * 设置应该与 {@link RestTemplate} 一起使用的 {@link HttpMessageConverter HttpMessageConverters}。
	 * 设置此值将替换任何先前配置的转换器，在构建器上配置的任何转换器将替换 RestTemplate 的默认转换器。
	 * @param messageConverters 要设置的转换器
	 * @return 一个新的构建器实例
	 * @see #additionalMessageConverters(HttpMessageConverter...)
	 */
	public RestTemplateBuilder messageConverters(Collection<? extends HttpMessageConverter<?>> messageConverters) {
		Assert.notNull(messageConverters, "MessageConverters must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				copiedSetOf(messageConverters), this.interceptors, this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, this.basicAuthentication, this.defaultHeaders, this.customizers,
				this.requestCustomizers);
	}

	/**
	 * 添加应该与 {@link RestTemplate} 一起使用的额外 {@link HttpMessageConverter HttpMessageConverters}。
	 * 在构建器上配置的任何转换器将替换 RestTemplate 的默认转换器。
	 * @param messageConverters 要添加的转换器
	 * @return 一个新的构建器实例
	 * @see #messageConverters(HttpMessageConverter...)
	 */
	public RestTemplateBuilder additionalMessageConverters(HttpMessageConverter<?>... messageConverters) {
		Assert.notNull(messageConverters, "MessageConverters must not be null");
		return additionalMessageConverters(Arrays.asList(messageConverters));
	}

	/**
	 * 添加应该与 {@link RestTemplate} 一起使用的额外 {@link HttpMessageConverter HttpMessageConverters}。
	 * 在构建器上配置的任何转换器将替换 RestTemplate 的默认转换器。
	 * @param messageConverters 要添加的转换器
	 * @return 一个新的构建器实例
	 * @see #messageConverters(HttpMessageConverter...)
	 */
	public RestTemplateBuilder additionalMessageConverters(
			Collection<? extends HttpMessageConverter<?>> messageConverters) {
		Assert.notNull(messageConverters, "MessageConverters must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				append(this.messageConverters, messageConverters), this.interceptors, this.requestFactory,
				this.uriTemplateHandler, this.errorHandler, this.basicAuthentication, this.defaultHeaders,
				this.customizers, this.requestCustomizers);
	}

	/**
	 * 将应该与 {@link RestTemplate} 一起使用的 {@link HttpMessageConverter HttpMessageConverters}
	 * 设置为默认集合。调用此方法将替换任何先前定义的转换器。
	 * @return 一个新的构建器实例
	 * @see #messageConverters(HttpMessageConverter...)
	 */
	public RestTemplateBuilder defaultMessageConverters() {
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				copiedSetOf(new RestTemplate().getMessageConverters()), this.interceptors, this.requestFactory,
				this.uriTemplateHandler, this.errorHandler, this.basicAuthentication, this.defaultHeaders,
				this.customizers, this.requestCustomizers);
	}

	/**
	 * 设置应该与 {@link RestTemplate} 一起使用的 {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors}。
	 * 设置此值将替换任何先前定义的拦截器。
	 * @param interceptors 要设置的拦截器
	 * @return 一个新的构建器实例
	 * @since 1.4.1
	 * @see #additionalInterceptors(ClientHttpRequestInterceptor...)
	 */
	public RestTemplateBuilder interceptors(ClientHttpRequestInterceptor... interceptors) {
		Assert.notNull(interceptors, "interceptors must not be null");
		return interceptors(Arrays.asList(interceptors));
	}

	/**
	 * 设置应该与 {@link RestTemplate} 一起使用的 {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors}。
	 * 设置此值将替换任何先前定义的拦截器。
	 * @param interceptors 要设置的拦截器
	 * @return 一个新的构建器实例
	 * @since 1.4.1
	 * @see #additionalInterceptors(ClientHttpRequestInterceptor...)
	 */
	public RestTemplateBuilder interceptors(Collection<ClientHttpRequestInterceptor> interceptors) {
		Assert.notNull(interceptors, "interceptors must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, copiedSetOf(interceptors), this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, this.basicAuthentication, this.defaultHeaders, this.customizers,
				this.requestCustomizers);
	}

	/**
	 * 添加应该与 {@link RestTemplate} 一起使用的额外 {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors}。
	 * @param interceptors 要添加的拦截器
	 * @return 一个新的构建器实例
	 * @since 1.4.1
	 * @see #interceptors(ClientHttpRequestInterceptor...)
	 */
	public RestTemplateBuilder additionalInterceptors(ClientHttpRequestInterceptor... interceptors) {
		Assert.notNull(interceptors, "interceptors must not be null");
		return additionalInterceptors(Arrays.asList(interceptors));
	}

	/**
	 * 添加应该与 {@link RestTemplate} 一起使用的额外 {@link ClientHttpRequestInterceptor ClientHttpRequestInterceptors}。
	 * @param interceptors 要添加的拦截器
	 * @return 一个新的构建器实例
	 * @since 1.4.1
	 * @see #interceptors(ClientHttpRequestInterceptor...)
	 */
	public RestTemplateBuilder additionalInterceptors(Collection<? extends ClientHttpRequestInterceptor> interceptors) {
		Assert.notNull(interceptors, "interceptors must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, append(this.interceptors, interceptors), this.requestFactory,
				this.uriTemplateHandler, this.errorHandler, this.basicAuthentication, this.defaultHeaders,
				this.customizers, this.requestCustomizers);
	}

	/**
	 * 设置应该与 {@link RestTemplate} 一起使用的 {@link ClientHttpRequestFactory} 类。
	 * @param requestFactory 要使用的请求工厂
	 * @return 一个新的构建器实例
	 */
	public RestTemplateBuilder requestFactory(Class<? extends ClientHttpRequestFactory> requestFactory) {
		Assert.notNull(requestFactory, "RequestFactory must not be null");
		return requestFactory(() -> createRequestFactory(requestFactory));
	}

	private ClientHttpRequestFactory createRequestFactory(Class<? extends ClientHttpRequestFactory> requestFactory) {
		try {
			Constructor<?> constructor = requestFactory.getDeclaredConstructor();
			constructor.setAccessible(true);
			return (ClientHttpRequestFactory) constructor.newInstance();
		}
		catch (Exception ex) {
			throw new IllegalStateException(ex);
		}
	}

	/**
	 * 设置每次我们 {@link #build()} 一个新的 {@link RestTemplate} 实例时应该调用的
	 * {@link ClientHttpRequestFactory} 的 {@code Supplier}。
	 * @param requestFactory 请求工厂的供应商
	 * @return 一个新的构建器实例
	 * @since 2.0.0
	 */
	public RestTemplateBuilder requestFactory(Supplier<ClientHttpRequestFactory> requestFactory) {
		Assert.notNull(requestFactory, "RequestFactory Supplier must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, requestFactory, this.uriTemplateHandler, this.errorHandler,
				this.basicAuthentication, this.defaultHeaders, this.customizers, this.requestCustomizers);
	}

	/**
	 * 设置应该与 {@link RestTemplate} 一起使用的 {@link UriTemplateHandler}。
	 * @param uriTemplateHandler 要使用的 URI 模板处理器
	 * @return 一个新的构建器实例
	 */
	public RestTemplateBuilder uriTemplateHandler(UriTemplateHandler uriTemplateHandler) {
		Assert.notNull(uriTemplateHandler, "UriTemplateHandler must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, uriTemplateHandler, this.errorHandler,
				this.basicAuthentication, this.defaultHeaders, this.customizers, this.requestCustomizers);
	}

	/**
	 * 设置应该与 {@link RestTemplate} 一起使用的 {@link ResponseErrorHandler}。
	 * @param errorHandler 要使用的错误处理器
	 * @return 一个新的构建器实例
	 */
	public RestTemplateBuilder errorHandler(ResponseErrorHandler errorHandler) {
		Assert.notNull(errorHandler, "ErrorHandler must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler, errorHandler,
				this.basicAuthentication, this.defaultHeaders, this.customizers, this.requestCustomizers);
	}

	/**
	 * 为请求添加HTTP基本认证，使用给定的用户名/密码对，
	 * 除非之前已经设置了自定义的Authorization头部。
	 * @param username 用户名
	 * @param password 密码
	 * @return 一个新的构建器实例
	 * @since 2.1.0
	 * @see #basicAuthentication(String, String, Charset)
	 */
	public RestTemplateBuilder basicAuthentication(String username, String password) {
		return basicAuthentication(username, password, null);
	}

	/**
	 * 为请求添加HTTP基本认证，使用给定的用户名/密码对，
	 * 除非之前已经设置了自定义的Authorization头部。
	 * @param username 用户名
	 * @param password 密码
	 * @param charset 要使用的字符集
	 * @return 一个新的构建器实例
	 * @since 2.2.0
	 */
	public RestTemplateBuilder basicAuthentication(String username, String password, Charset charset) {
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, new BasicAuthentication(username, password, charset), this.defaultHeaders,
				this.customizers, this.requestCustomizers);
	}

	/**
	 * 添加一个默认头部，如果在传出的 {@link HttpClientRequest} 中尚未存在，则会设置该头部。
	 * @param name 头部的名称
	 * @param values 头部的值
	 * @return 一个新的构建器实例
	 * @since 2.2.0
	 */
	public RestTemplateBuilder defaultHeader(String name, String... values) {
		Assert.notNull(name, "Name must not be null");
		Assert.notNull(values, "Values must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, this.basicAuthentication, append(this.defaultHeaders, name, values),
				this.customizers, this.requestCustomizers);
	}

	/**
	 * 设置底层 {@link ClientHttpRequestFactory} 的连接超时时间。
	 * @param connectTimeout 连接超时时间
	 * @return 一个新的构建器实例。
	 * @since 2.1.0
	 */
	public RestTemplateBuilder setConnectTimeout(Duration connectTimeout) {
		return new RestTemplateBuilder(this.requestFactoryCustomizer.connectTimeout(connectTimeout),
				this.detectRequestFactory, this.rootUri, this.messageConverters, this.interceptors, this.requestFactory,
				this.uriTemplateHandler, this.errorHandler, this.basicAuthentication, this.defaultHeaders,
				this.customizers, this.requestCustomizers);
	}

	/**
	 * 设置底层 {@link ClientHttpRequestFactory} 的读取超时时间。
	 * @param readTimeout 读取超时时间
	 * @return 一个新的构建器实例。
	 * @since 2.1.0
	 */
	public RestTemplateBuilder setReadTimeout(Duration readTimeout) {
		return new RestTemplateBuilder(this.requestFactoryCustomizer.readTimeout(readTimeout),
				this.detectRequestFactory, this.rootUri, this.messageConverters, this.interceptors, this.requestFactory,
				this.uriTemplateHandler, this.errorHandler, this.basicAuthentication, this.defaultHeaders,
				this.customizers, this.requestCustomizers);
	}

	/**
	 * 设置底层的 {@link ClientHttpRequestFactory} 是否应该在内部缓冲
	 * {@linkplain ClientHttpRequest#getBody() 请求体}。
	 * @param bufferRequestBody bufferRequestBody 参数的值
	 * @return 一个新的构建器实例。
	 * @since 2.2.0
	 * @see SimpleClientHttpRequestFactory#setBufferRequestBody(boolean)
	 * @see HttpComponentsClientHttpRequestFactory#setBufferRequestBody(boolean)
	 */
	public RestTemplateBuilder setBufferRequestBody(boolean bufferRequestBody) {
		return new RestTemplateBuilder(this.requestFactoryCustomizer.bufferRequestBody(bufferRequestBody),
				this.detectRequestFactory, this.rootUri, this.messageConverters, this.interceptors, this.requestFactory,
				this.uriTemplateHandler, this.errorHandler, this.basicAuthentication, this.defaultHeaders,
				this.customizers, this.requestCustomizers);
	}

	/**
	 * 设置应该应用于 {@link RestTemplate} 的 {@link RestTemplateCustomizer RestTemplateCustomizers}。
	 * 定制器在构建器配置应用后按照它们被添加的顺序应用。设置此值将替换任何先前配置的定制器。
	 * @param customizers 要设置的定制器
	 * @return 一个新的构建器实例
	 * @see #additionalCustomizers(RestTemplateCustomizer...)
	 */
	public RestTemplateBuilder customizers(RestTemplateCustomizer... customizers) {
		Assert.notNull(customizers, "Customizers must not be null");
		return customizers(Arrays.asList(customizers));
	}

	/**
	 * 设置应该应用于 {@link RestTemplate} 的 {@link RestTemplateCustomizer RestTemplateCustomizers}。
	 * 定制器在构建器配置应用后按照它们被添加的顺序应用。设置此值将替换任何先前配置的定制器。
	 * @param customizers 要设置的定制器
	 * @return 一个新的构建器实例
	 * @see #additionalCustomizers(RestTemplateCustomizer...)
	 */
	public RestTemplateBuilder customizers(Collection<? extends RestTemplateCustomizer> customizers) {
		Assert.notNull(customizers, "Customizers must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, this.basicAuthentication, this.defaultHeaders, copiedSetOf(customizers),
				this.requestCustomizers);
	}

	/**
	 * 添加应该应用于 {@link RestTemplate} 的 {@link RestTemplateCustomizer RestTemplateCustomizers}。
	 * 定制器在构建器配置应用后按照它们被添加的顺序应用。
	 * @param customizers 要添加的定制器
	 * @return 一个新的构建器实例
	 * @see #customizers(RestTemplateCustomizer...)
	 */
	public RestTemplateBuilder additionalCustomizers(RestTemplateCustomizer... customizers) {
		Assert.notNull(customizers, "Customizers must not be null");
		return additionalCustomizers(Arrays.asList(customizers));
	}

	/**
	 * 添加应该应用于 {@link RestTemplate} 的 {@link RestTemplateCustomizer RestTemplateCustomizers}。
	 * 定制器在构建器配置应用后按照它们被添加的顺序应用。
	 * @param customizers 要添加的定制器
	 * @return 一个新的构建器实例
	 * @see #customizers(RestTemplateCustomizer...)
	 */
	public RestTemplateBuilder additionalCustomizers(Collection<? extends RestTemplateCustomizer> customizers) {
		Assert.notNull(customizers, "RestTemplateCustomizers must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, this.basicAuthentication, this.defaultHeaders, append(this.customizers, customizers),
				this.requestCustomizers);
	}

	/**
	 * 设置应该应用于 {@link ClientHttpRequest} 的 {@link RestTemplateRequestCustomizer RestTemplateRequestCustomizers}。
	 * 定制器按照它们被添加的顺序应用。设置此值将替换任何先前配置的请求定制器。
	 * @param requestCustomizers 要设置的请求定制器
	 * @return 一个新的构建器实例
	 * @since 2.2.0
	 * @see #additionalRequestCustomizers(RestTemplateRequestCustomizer...)
	 */
	public RestTemplateBuilder requestCustomizers(RestTemplateRequestCustomizer<?>... requestCustomizers) {
		Assert.notNull(requestCustomizers, "RequestCustomizers must not be null");
		return requestCustomizers(Arrays.asList(requestCustomizers));
	}

	/**
	 * 设置应该应用于 {@link ClientHttpRequest} 的 {@link RestTemplateRequestCustomizer RestTemplateRequestCustomizers}。
	 * 定制器按照它们被添加的顺序应用。设置此值将替换任何先前配置的请求定制器。
	 * @param requestCustomizers 要设置的请求定制器
	 * @return 一个新的构建器实例
	 * @since 2.2.0
	 * @see #additionalRequestCustomizers(RestTemplateRequestCustomizer...)
	 */
	public RestTemplateBuilder requestCustomizers(
			Collection<? extends RestTemplateRequestCustomizer<?>> requestCustomizers) {
		Assert.notNull(requestCustomizers, "RequestCustomizers must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, this.basicAuthentication, this.defaultHeaders, this.customizers,
				copiedSetOf(requestCustomizers));
	}

	/**
	 * 添加应该应用于 {@link ClientHttpRequest} 的 {@link RestTemplateRequestCustomizer RestTemplateRequestCustomizers}。
	 * 定制器按照它们被添加的顺序应用。
	 * @param requestCustomizers 要添加的请求定制器
	 * @return 一个新的构建器实例
	 * @since 2.2.0
	 * @see #requestCustomizers(RestTemplateRequestCustomizer...)
	 */
	public RestTemplateBuilder additionalRequestCustomizers(RestTemplateRequestCustomizer<?>... requestCustomizers) {
		Assert.notNull(requestCustomizers, "RequestCustomizers must not be null");
		return additionalRequestCustomizers(Arrays.asList(requestCustomizers));
	}

	/**
	 * 添加应该应用于 {@link ClientHttpRequest} 的 {@link RestTemplateRequestCustomizer RestTemplateRequestCustomizers}。
	 * 定制器按照它们被添加的顺序应用。
	 * @param requestCustomizers 要添加的请求定制器
	 * @return 一个新的构建器实例
	 * @since 2.2.0
	 * @see #requestCustomizers(Collection)
	 */
	public RestTemplateBuilder additionalRequestCustomizers(
			Collection<? extends RestTemplateRequestCustomizer<?>> requestCustomizers) {
		Assert.notNull(requestCustomizers, "RequestCustomizers must not be null");
		return new RestTemplateBuilder(this.requestFactoryCustomizer, this.detectRequestFactory, this.rootUri,
				this.messageConverters, this.interceptors, this.requestFactory, this.uriTemplateHandler,
				this.errorHandler, this.basicAuthentication, this.defaultHeaders, this.customizers,
				append(this.requestCustomizers, requestCustomizers));
	}

	/**
	 * 构建一个新的 {@link RestTemplate} 实例并使用此构建器进行配置。
	 * @return 一个已配置的 {@link RestTemplate} 实例。
	 * @see #build(Class)
	 * @see #configure(RestTemplate)
	 */
	public RestTemplate build() {
		return configure(new RestTemplate());
	}

	/**
	 * 构建一个指定类型的新 {@link RestTemplate} 实例并使用此构建器进行配置。
	 * @param <T> rest template 的类型
	 * @param restTemplateClass 要创建的模板类型
	 * @return 一个已配置的 {@link RestTemplate} 实例。
	 * @see RestTemplateBuilder#build()
	 * @see #configure(RestTemplate)
	 */
	public <T extends RestTemplate> T build(Class<T> restTemplateClass) {
		return configure(BeanUtils.instantiateClass(restTemplateClass));
	}

	/**
	 * 使用此构建器配置提供的 {@link RestTemplate} 实例。
	 * @param <T> rest template 的类型
	 * @param restTemplate 要配置的 {@link RestTemplate}
	 * @return rest template 实例
	 * @see RestTemplateBuilder#build()
	 * @see RestTemplateBuilder#build(Class)
	 */
	public <T extends RestTemplate> T configure(T restTemplate) {
		ClientHttpRequestFactory requestFactory = buildRequestFactory();
		if (requestFactory != null) {
			restTemplate.setRequestFactory(requestFactory);
		}
		addClientHttpRequestInitializer(restTemplate);
		if (!CollectionUtils.isEmpty(this.messageConverters)) {
			restTemplate.setMessageConverters(new ArrayList<>(this.messageConverters));
		}
		if (this.uriTemplateHandler != null) {
			restTemplate.setUriTemplateHandler(this.uriTemplateHandler);
		}
		if (this.errorHandler != null) {
			restTemplate.setErrorHandler(this.errorHandler);
		}
		if (this.rootUri != null) {
			RootUriTemplateHandler.addTo(restTemplate, this.rootUri);
		}
		restTemplate.getInterceptors().addAll(this.interceptors);
		if (!CollectionUtils.isEmpty(this.customizers)) {
			for (RestTemplateCustomizer customizer : this.customizers) {
				customizer.customize(restTemplate);
			}
		}
		return restTemplate;
	}

	/**
	 * 使用此构建器的设置创建一个新的 {@link ClientHttpRequestFactory} 实例。
	 * @return 一个 {@link ClientHttpRequestFactory} 实例或 {@code null}
	 * @since 2.2.0
	 */
	public ClientHttpRequestFactory buildRequestFactory() {
		ClientHttpRequestFactory requestFactory = null;
		if (this.requestFactory != null) {
			requestFactory = this.requestFactory.get();
		}
		else if (this.detectRequestFactory) {
			requestFactory = new ClientHttpRequestFactorySupplier().get();
		}
		if (requestFactory != null) {
			if (this.requestFactoryCustomizer != null) {
				this.requestFactoryCustomizer.accept(requestFactory);
			}
		}
		return requestFactory;
	}

	private void addClientHttpRequestInitializer(RestTemplate restTemplate) {
		if (this.basicAuthentication == null && this.defaultHeaders.isEmpty() && this.requestCustomizers.isEmpty()) {
			return;
		}
		restTemplate.getClientHttpRequestInitializers().add(new RestTemplateBuilderClientHttpRequestInitializer(
				this.basicAuthentication, this.defaultHeaders, this.requestCustomizers));
	}

	@SuppressWarnings("unchecked")
	private <T> Set<T> copiedSetOf(T... items) {
		return copiedSetOf(Arrays.asList(items));
	}

	private <T> Set<T> copiedSetOf(Collection<? extends T> collection) {
		return Collections.unmodifiableSet(new LinkedHashSet<>(collection));
	}

	private static <T> List<T> copiedListOf(T[] items) {
		return Collections.unmodifiableList(Arrays.asList(Arrays.copyOf(items, items.length)));
	}

	private static <T> Set<T> append(Collection<? extends T> collection, Collection<? extends T> additions) {
		Set<T> result = new LinkedHashSet<>((collection != null) ? collection : Collections.emptySet());
		if (additions != null) {
			result.addAll(additions);
		}
		return Collections.unmodifiableSet(result);
	}

	private static <K, V> Map<K, List<V>> append(Map<K, List<V>> map, K key, V[] values) {
		Map<K, List<V>> result = new LinkedHashMap<>((map != null) ? map : Collections.emptyMap());
		if (values != null) {
			result.put(key, copiedListOf(values));
		}
		return Collections.unmodifiableMap(result);
	}

	/**
	 * 用于应用 {@link ClientHttpRequestFactory} 设置的内部自定义器。
	 */
	private static class RequestFactoryCustomizer implements Consumer<ClientHttpRequestFactory> {

		private final Duration connectTimeout;

		private final Duration readTimeout;

		private final Boolean bufferRequestBody;

		RequestFactoryCustomizer() {
			this(null, null, null);
		}

		private RequestFactoryCustomizer(Duration connectTimeout, Duration readTimeout, Boolean bufferRequestBody) {
			this.connectTimeout = connectTimeout;
			this.readTimeout = readTimeout;
			this.bufferRequestBody = bufferRequestBody;
		}

		RequestFactoryCustomizer connectTimeout(Duration connectTimeout) {
			return new RequestFactoryCustomizer(connectTimeout, this.readTimeout, this.bufferRequestBody);
		}

		RequestFactoryCustomizer readTimeout(Duration readTimeout) {
			return new RequestFactoryCustomizer(this.connectTimeout, readTimeout, this.bufferRequestBody);
		}

		RequestFactoryCustomizer bufferRequestBody(boolean bufferRequestBody) {
			return new RequestFactoryCustomizer(this.connectTimeout, this.readTimeout, bufferRequestBody);
		}

		@Override
		public void accept(ClientHttpRequestFactory requestFactory) {
			ClientHttpRequestFactory unwrappedRequestFactory = unwrapRequestFactoryIfNecessary(requestFactory);
			if (this.connectTimeout != null) {
				setConnectTimeout(unwrappedRequestFactory);
			}
			if (this.readTimeout != null) {
				setReadTimeout(unwrappedRequestFactory);
			}
			if (this.bufferRequestBody != null) {
				setBufferRequestBody(unwrappedRequestFactory);
			}
		}

		private ClientHttpRequestFactory unwrapRequestFactoryIfNecessary(ClientHttpRequestFactory requestFactory) {
			if (!(requestFactory instanceof AbstractClientHttpRequestFactoryWrapper)) {
				return requestFactory;
			}
			Field field = ReflectionUtils.findField(AbstractClientHttpRequestFactoryWrapper.class, "requestFactory");
			ReflectionUtils.makeAccessible(field);
			ClientHttpRequestFactory unwrappedRequestFactory = requestFactory;
			while (unwrappedRequestFactory instanceof AbstractClientHttpRequestFactoryWrapper) {
				unwrappedRequestFactory = (ClientHttpRequestFactory) ReflectionUtils.getField(field,
						unwrappedRequestFactory);
			}
			return unwrappedRequestFactory;
		}

		private void setConnectTimeout(ClientHttpRequestFactory factory) {
			Method method = findMethod(factory, "setConnectTimeout", int.class);
			int timeout = Math.toIntExact(this.connectTimeout.toMillis());
			invoke(factory, method, timeout);
		}

		private void setReadTimeout(ClientHttpRequestFactory factory) {
			Method method = findMethod(factory, "setReadTimeout", int.class);
			int timeout = Math.toIntExact(this.readTimeout.toMillis());
			invoke(factory, method, timeout);
		}

		private void setBufferRequestBody(ClientHttpRequestFactory factory) {
			Method method = findMethod(factory, "setBufferRequestBody", boolean.class);
			invoke(factory, method, this.bufferRequestBody);
		}

		private Method findMethod(ClientHttpRequestFactory requestFactory, String methodName, Class<?>... parameters) {
			Method method = ReflectionUtils.findMethod(requestFactory.getClass(), methodName, parameters);
			if (method != null) {
				return method;
			}
			throw new IllegalStateException("Request factory " + requestFactory.getClass()
					+ " does not have a suitable " + methodName + " method");
		}

		private void invoke(ClientHttpRequestFactory requestFactory, Method method, Object... parameters) {
			ReflectionUtils.invokeMethod(method, requestFactory, parameters);
		}

	}

}
